package com.cennavi.minemap.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cennavi.minemap.util.GeoUtil;
import com.cennavi.minemap.util.HttpClientUtil;
import com.cennavi.minemap.util.StringUtil;
import com.cennavi.minemap.util.TNaviTurnIconID;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import org.apache.http.client.ClientProtocolException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@ComponentScan(basePackages = {"com.cennavi.minemap.util"})
@PropertySource(value = {"classpath:application.properties"})
public class MapbarService {

    private static int HUNDRED_THOUSAND = 100000;
    /* 行政区信息查询时, 若未给定坐标, 默认使用北京中心点坐标 */
    private static final String ADMIN_BEIJING_CENTER_LOCATION = "116.3975,39.908681";

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Value("${spring.service.mapbar.search.url}")
    private String searchUrl;
    @Value("${spring.service.mapbar.inverse.url}")
    private String reverseGeocoding;
    @Value("${spring.service.mapbar.bus.url}")
    private String busUrl;
    @Value("${spring.service.mapbar.qfroute.url}")
    private String qfrouteUrl;
    @Value("${spring.service.mapbar.route.url}")
    private String routeUrl;
    @Value("${spring.service.mapbar.newRoute.url}")
    private String newRouteUrl;
    private GeometryFactory factory = new GeometryFactory();

    public String keyword(String city, String keywords, Integer page_num, Integer page_size)
            throws ClientProtocolException, IOException {

        String allUrl = searchUrl + "keywords?keywords=" + keywords;

        if (city != null) {
            allUrl = allUrl + "&city=" + city;
        }
        if (page_num != null) {
            allUrl = allUrl + "&page_num=" + page_num;
        }
        if (page_size != null) {
            allUrl = allUrl + "&page_size=" + page_size;
        }

        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);

        JSONObject data = new JSONObject();

        data.put("pageCount", page_size);
        data.put("totalCount", result.get("total"));
        data.put("page_num", page_num);

        JSONObject currentDistrict = result.getJSONObject("currentDistrict");

        JSONArray rows = new JSONArray();

        for (int i = 0; i < result.getJSONArray("pois").size(); i++) {
            JSONObject row = new JSONObject();
            JSONObject poi = (JSONObject) result.getJSONArray("pois").get(i);
            String location = poi.getString("location");
            Point point = factory.createPoint(new Coordinate(Double.parseDouble(location.split(",")[0]),
                    Double.parseDouble(location.split(",")[1])));
            row.put("id", poi.get("nid"));

            row.put("province", poi.get("province"));
            row.put("city", poi.get("city"));
            row.put("district", poi.get("district"));

            row.put("dataType", "");
            row.put("resultType", "");
            row.put("distance", poi.get("distance"));
            row.put("name", poi.get("name"));
            row.put("address", poi.get("address"));
            row.put("tel", poi.get("phone"));
            row.put("adcode", currentDistrict.get("adcode"));
            row.put("geom", JSONObject.parse(GeoUtil.writeGeojson(point)));
            row.put("geom_display", JSONObject.parse(GeoUtil.writeGeojson(point)));
            rows.add(row);
        }
        data.put("rows", rows);
        return data.toJSONString();
    }

    public String surround(String keywords, Integer page_num, Integer page_size, String location, Integer range,
                           String city) throws ClientProtocolException, IOException {

        String allUrl = searchUrl + "around?keywords=" + keywords + "&location=" + location + "&range=" + range;

        if (city != null) {
            allUrl = allUrl + "&city=" + city;
        }
        if (page_num != null) {
            allUrl = allUrl + "&page_num=" + page_num;
        }
        if (page_size != null) {
            allUrl = allUrl + "&page_size=" + page_size;
        }
        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);

        JSONObject data = new JSONObject();

        data.put("pageCount", page_size);
        data.put("totalCount", result.get("total"));
        data.put("page_num", page_num);

        JSONObject currentDistrict = result.getJSONObject("currentDistrict");

        JSONArray rows = new JSONArray();

        for (int i = 0; i < result.getJSONArray("pois").size(); i++) {
            JSONObject row = new JSONObject();
            JSONObject poi = (JSONObject) result.getJSONArray("pois").get(i);
            String _location = poi.getString("location");
            Point point = factory.createPoint(new Coordinate(Double.parseDouble(_location.split(",")[0]),
                    Double.parseDouble(_location.split(",")[1])));
            row.put("id", poi.get("nid"));

            row.put("province", poi.get("province"));
            row.put("city", poi.get("city"));
            row.put("district", poi.get("district"));

            row.put("dataType", "");
            row.put("resultType", "");
            row.put("distance", poi.get("distance"));
            row.put("name", poi.get("name"));
            row.put("address", poi.get("address"));
            row.put("tel", poi.get("phone"));
            row.put("adcode", currentDistrict.get("adcode"));
            row.put("geom", JSONObject.parse(GeoUtil.writeGeojson(point)));
            row.put("geom_display", JSONObject.parse(GeoUtil.writeGeojson(point)));
            rows.add(row);
        }
        data.put("rows", rows);
        return data.toJSONString();
    }

    public String bbox(String city, String key, Integer page_num, Integer page_size, Double lon1, Double lat1,
                       Double lon2, Double lat2) throws ClientProtocolException, IOException {
        String allUrl = searchUrl + "area?keywords=" + key;

        if (city != null) {
            allUrl = allUrl + "&city=" + city;
        }
        if (page_num != null) {
            allUrl = allUrl + "&page_num=" + page_num;
        }
        if (page_size != null) {
            allUrl = allUrl + "&page_size=" + page_size;
        }

        String area = URLEncoder.encode(lon1 + "," + lat1 + ";" + lon2 + "," + lat2, "utf-8");

        allUrl = allUrl + "&area=" + area;

        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);

        JSONObject data = new JSONObject();

        data.put("pageCount", page_size);
        data.put("totalCount", result.get("total"));
        data.put("page_num", page_num);

        JSONObject currentDistrict = result.getJSONObject("currentDistrict");

        JSONArray rows = new JSONArray();

        for (int i = 0; i < result.getJSONArray("pois").size(); i++) {
            JSONObject row = new JSONObject();
            JSONObject poi = (JSONObject) result.getJSONArray("pois").get(i);
            String location = poi.getString("location");
            Point point = factory.createPoint(new Coordinate(Double.parseDouble(location.split(",")[0]),
                    Double.parseDouble(location.split(",")[1])));
            row.put("id", poi.get("nid"));

            row.put("province", poi.get("province"));
            row.put("city", poi.get("city"));
            row.put("district", poi.get("district"));

            row.put("dataType", "");
            row.put("resultType", "");
            row.put("distance", poi.get("distance"));
            row.put("name", poi.get("name"));
            row.put("address", poi.get("address"));
            row.put("tel", poi.get("phone"));
            row.put("adcode", currentDistrict.get("adcode"));
            row.put("geom", JSONObject.parse(GeoUtil.writeGeojson(point)));
            row.put("geom_display", JSONObject.parse(GeoUtil.writeGeojson(point)));
            rows.add(row);
        }
        data.put("rows", rows);
        return data.toJSONString();
    }

    /**
     * 地理编码 POI 查询(新)
     * <p>
     * 新接口{@link MapbarService#geocoding2(java.lang.String, java.lang.String, java.lang.Integer, java.lang.Integer)}
     */
    public String geocoding(String keywords, String adCode) throws ClientProtocolException, IOException {
        String allUrl = searchUrl + "keywords?keywords=" + URLEncoder.encode(keywords, "utf-8");

        if (adCode != null) {
            allUrl = allUrl + "&city=" + adCode;
        }
        allUrl = allUrl + "&page_num=1";
        allUrl = allUrl + "&page_size=10";

        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);
        JSONObject data = new JSONObject();
        JSONObject currentDistrict = result.getJSONObject("currentDistrict");
        JSONArray rows = new JSONArray();

        for (int i = 0; i < result.getJSONArray("pois").size(); i++) {
            JSONObject row = new JSONObject();
            JSONObject poi = (JSONObject) result.getJSONArray("pois").get(i);
            String location = poi.getString("location");
            row.put("name", poi.get("name"));
            row.put("address", poi.get("address"));
            row.put("adcode", currentDistrict.get("adcode"));
            row.put("lon", Double.parseDouble(location.split(",")[0]));
            row.put("lat", Double.parseDouble(location.split(",")[1]));
            row.put("geotype", 0);
            row.put("geolevel", 0);
            rows.add(row);
        }
        data.put("rows", rows);
        return data.toJSONString();
    }

    /**
     * 地理编码评分
     * <p>
     * 新版本方法{@link MapbarService#geocodingScore2(java.lang.String, java.lang.String)}
     */
    @Deprecated
    public String geocodingScore(String keywords, String adCode)
            throws ClientProtocolException, IOException {
        String allUrl = searchUrl + "geo?keywords=" + URLEncoder.encode(keywords, "utf-8");

        if (adCode != null && !adCode.equals("")) {
            allUrl = allUrl + "&city=" + adCode;
        }
        allUrl = allUrl + "&search_type=for_simple";

        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);
        JSONObject data = new JSONObject();
        JSONObject geo = result.getJSONObject("geo");

        JSONObject currentDistrict = result.getJSONObject("currentDistrict");

        JSONArray rows = new JSONArray();
        JSONObject row = new JSONObject();
        row.put("location", geo.getString("location"));
        row.put("score", geo.getDouble("score"));
        row.put("adname", currentDistrict.getString("name"));
        row.put("adcode", currentDistrict.getString("adcode"));
        rows.add(row);

        data.put("rows", rows);
        return data.toJSONString();
    }

    /**
     * 逆地理编码查询
     * <p>
     * 新版本{@link MapbarService#reverseGeocoding2(java.lang.Double, java.lang.Double, java.lang.Integer, java.lang.Integer, java.lang.Integer)}
     *
     * @param lon
     * @param lat
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    @Deprecated
    public String reverseGeocoding(Double lon, Double lat) throws ClientProtocolException, IOException {
        String allUrl = reverseGeocoding
                + "getInverseGeocoding.json?detail=1&zoom=11&latlon=&customer=2&rowNumber=1&lat=" + lat + "&lon=" + lon;
        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);
        JSONObject data = new JSONObject();

        JSONObject poies = result.getJSONObject("poies");
        JSONArray poiItemList = poies.getJSONArray("poiItemList");
        JSONObject poiItem = poiItemList.getJSONObject(0);

        JSONObject province = result.getJSONObject("province");
        JSONObject city = result.getJSONObject("city");
        JSONObject dist = result.getJSONObject("dist");
        JSONObject town = result.getJSONObject("town");
        JSONObject village = result.getJSONObject("village");

        data.put("id", poiItem.getString("pid"));
        data.put("adcode", dist.getString("code"));
        data.put("roadname", "");
        data.put("restName", poiItem.getString("poi"));
        data.put("type", "poi");
        data.put("distance", poiItem.getString("distance"));

        data.put("province", province.get("value"));
        data.put("city", city.get("value"));
        data.put("dist", dist.get("value"));

        if (town != null) {
            data.put("town", town.get("value"));
        } else {
            data.put("town", null);
        }

        if (village != null) {
            data.put("village", village.get("value"));
        } else {
            data.put("village", null);
        }

        return data.toJSONString();
    }

    public String adminByPoint(Double lon, Double lat) throws ClientProtocolException, IOException {
        String allUrl = reverseGeocoding + "getInverseGeocoding.json?"
                + "detail=1&zoom=11&latlon=&customer=2&rowNumber=1&lat=" + lat + "&lon=" + lon;

        String response = HttpClientUtil.doGet(allUrl);
        JSONObject object = JSONObject.parseObject(response);

        JSONObject province = object.getJSONObject("province");
        JSONObject city = object.getJSONObject("city");
        JSONObject dist = object.getJSONObject("dist");

        JSONObject result = new JSONObject();
        result.put("centerlon", Double.parseDouble(dist.getString("center").split(",")[0]));
        result.put("centerlat", Double.parseDouble(dist.getString("center").split(",")[1]));
        result.put("province", province.getString("value"));
        result.put("city", city.getString("value"));
        result.put("areaname", dist.getString("value"));
        result.put("adcode", dist.getString("code"));
        return result.toJSONString();
    }

    public String getCityCode(Double lon, Double lat) throws ClientProtocolException, IOException {
        String allUrl = reverseGeocoding + "getInverseGeocoding.json?"
                + "detail=1&zoom=11&latlon=&customer=2&rowNumber=1&lat=" + lat + "&lon=" + lon;
        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);
        JSONObject city = result.getJSONObject("city");

        return city.getString("value");
    }

    public String getCityCode(String point) throws ClientProtocolException, IOException {
        double lon = Double.parseDouble(point.split(",")[0]);
        double lat = Double.parseDouble(point.split(",")[1]);
        return getCityCode(lon, lat);
    }

    public String driving(String orig, String dest, String style, String source)
            throws ClientProtocolException, IOException {
        String allUrl = "";
        if (source.equals("3")) {
            allUrl = qfrouteUrl + "getDriveByLatLon.json?width=500&height=430&encode=UTF-8&inGb=g02&outGb=g02&orig="
                    + orig + "&dest=" + dest;
        } else {
            allUrl = routeUrl + "routePlan.json?width=500&height=430&encode=UTF-8&inGb=g02&outGb=g02&orig=" + orig
                    + "&dest=" + dest;
        }

        if (style != null) {
            allUrl = allUrl + "&style=" + style;
        }
        System.out.println("route url:" + allUrl);
        JSONObject result = new JSONObject();

        String response = HttpClientUtil.doGet(allUrl);

        JSONArray rows = new JSONArray();
        rows.add(JSONObject.parseObject(response));

        result.put("rows", rows);

        return result.toJSONString();
    }

    /**
     * 路线规划
     * <p>
     * 新版本{@link MapbarService#newDriving2(java.lang.String, java.lang.String, java.lang.String, int, java.lang.String)}
     */
    // http://203.81.245.37:20080/nc/v1/routing?dv=2.1.4&sAddr=11635983,3991667&toAddr=11643177,3990494&flag=2,3,4,5,6,7,8,ts,10,linkId,11&rpet=2&pet=2
    public String newDriving(String sAddr, String toAddr, String wayPoints, int st, String avoidArea)
            throws ClientProtocolException, IOException {

        long start = System.currentTimeMillis();
        logger.info("start:{}", start);

        String allUrl;
        String slon = new BigDecimal(Double.parseDouble(sAddr.split(",")[0]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
        String slat = new BigDecimal(Double.parseDouble(sAddr.split(",")[1]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();

        String _wayPoints = "";

        if (wayPoints != null && !"".equals(wayPoints)) {
            for (int i = 0; i < wayPoints.split(";").length; i++) {
                String wayPoint = wayPoints.split(";")[i];
                String wlon = new BigDecimal(Double.parseDouble(wayPoint.split(",")[0]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String wlat = new BigDecimal(Double.parseDouble(wayPoint.split(",")[1]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                _wayPoints = _wayPoints + wlon + "," + wlat + ";";
            }
        }
        String tlon = new BigDecimal(Double.parseDouble(toAddr.split(",")[0]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
        String tlat = new BigDecimal(Double.parseDouble(toAddr.split(",")[1]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();

        String _toAddr = _wayPoints + tlon + "," + tlat;

        allUrl = newRouteUrl + "routing?dv=2.1.4&st=4&flag=2,3,4,5,6,7,8,ts,10,linkId,11&rpet=2&pet=2&sAddr=" + slon
                + "," + slat + "&toAddr=" + _toAddr;

        if (st == 2) {
            allUrl = allUrl + "&tmc=" + 1;
        } else {
            allUrl = allUrl + "&st=" + st;
        }
        if (avoidArea != null && !avoidArea.equals("")) {
            String avoidAreaStr = "";
            for (String avoid : avoidArea.split("\\|")) {
                String avoidLon1 = new BigDecimal(Double.parseDouble(avoid.split(",")[0]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLat1 = new BigDecimal(Double.parseDouble(avoid.split(",")[1]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLon2 = new BigDecimal(Double.parseDouble(avoid.split(",")[2]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLat2 = new BigDecimal(Double.parseDouble(avoid.split(",")[3]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                avoidAreaStr = avoidAreaStr + avoidLon1 + "," + avoidLon2 + "," + avoidLat2 + "," + avoidLat1 + "|";

                avoidAreaStr = replace(avoidAreaStr);
            }
            avoidAreaStr = avoidAreaStr.substring(0, avoidAreaStr.length() - 1);
            allUrl = allUrl + "&avoidArea=" + URLEncoder.encode(avoidAreaStr, "utf-8");
        }

        long step1 = System.currentTimeMillis();
        logger.info("构建请求 url:{}ms", step1 - start);

        String response = HttpClientUtil.doGet(allUrl);

        long step2 = System.currentTimeMillis();
        logger.info("请求耗时:{}ms", step2 - step1);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject result = object.getJSONArray("result").getJSONObject(0);
        JSONObject route = result.getJSONObject("route");
        JSONArray segm = route.getJSONArray("segm");
        String firstNM = segm.getJSONObject(0).getString("nm");

        int dur = route.getInteger("dur");
        int dis = route.getInteger("dis");

        /* 1. 构建 routelatlon */
        StringBuilder routelatlon = new StringBuilder();

        /* 2. 构建 items */
        JSONArray dir = route.getJSONArray("dir");

        Map<String, String> streetName = new HashMap<>();
        for (int i = 0; i < dir.size(); i++) {
            JSONObject _dir = dir.getJSONObject(i);
            streetName.put(_dir.getString("pos"), _dir.getString("nm"));
        }

        JSONArray rDD = route.getJSONArray("rDD");

        JSONArray items = new JSONArray();
        Integer tmcLv = 0;

        for (int i = 1; i <= rDD.size(); i++) {

            JSONObject _rDD;
            Integer chd = 0;
            Integer eSI = 0;
            if (i < rDD.size()) {
                _rDD = rDD.getJSONObject(i);
                chd = _rDD.getInteger("chd") == null ? 1 : 0;
                eSI = _rDD.getInteger("sSI");
            } else {
                eSI = segm.size();
            }
            JSONObject _preRDD = rDD.getJSONObject(i - 1);

            Integer prdChd = _preRDD.getInteger("chd") == null ? 1 : 0;
            if (prdChd == 0 && chd == 1) {
                // System.out.println("过滤" + i);
            } else {
                JSONObject item = new JSONObject();
                item.put("id", i - 1);

                if (i == 1) {
                    item.put("strguide", _preRDD.getString("tit").replace("{0}", firstNM));
                } else {
                    item.put("strguide", _preRDD.getString("tit").replace("{0}", ""));
                }

                String pos = _preRDD.getString("pos");
                Double lon = Double.parseDouble(pos.split(",")[0]) / HUNDRED_THOUSAND;
                Double lat = Double.parseDouble(pos.split(",")[1]) / HUNDRED_THOUSAND;
                item.put("turnlatlon", lon + "," + lat);
                item.put("distance", _preRDD.getInteger("dis"));

                int sSI = _preRDD.getInteger("sSI");
                List<Object> subSegm = segm.subList(sSI, eSI);

                item.put("sSI", sSI);
                item.put("eSI", eSI);

                if (subSegm.size() > 0) {
                    JSONArray tmc = new JSONArray();
                    String _routelatlon = "";
                    for (int j = 0; j < subSegm.size(); j++) {
                        JSONObject _segm = (JSONObject) subSegm.get(j);

                        String shPos = _segm.getString("shPos");

                        if (_segm.getInteger("tmcLv") != null)
                            tmcLv = _segm.getInteger("tmcLv");

                        String[] lonlat = shPos.split(";");

                        String linklatlon = "";
                        for (int k = 0; k < lonlat.length; k++) {
                            Double _lon = Double.parseDouble(lonlat[k].split(",")[0]) / HUNDRED_THOUSAND;
                            Double _lat = Double.parseDouble(lonlat[k].split(",")[1]) / HUNDRED_THOUSAND;
                            linklatlon = linklatlon + _lon + "," + _lat + ";";
                        }
                        JSONObject _tmc = new JSONObject();
                        _tmc.put("level", tmcLv);
                        _tmc.put("route", linklatlon);
                        tmc.add(_tmc);

                        int flag = j == 0 ? 0 : 1;
                        for (int k = flag; k < lonlat.length; k++) {
                            Double _lon = Double.parseDouble(lonlat[k].split(",")[0]) / HUNDRED_THOUSAND;
                            Double _lat = Double.parseDouble(lonlat[k].split(",")[1]) / HUNDRED_THOUSAND;
                            _routelatlon = _routelatlon + _lon + "," + _lat + ";";
                            routelatlon.append(_lon).append(",").append(_lat).append(";");
                        }
                    }
                    item.put("routelatlon", _routelatlon);
                    item.put("tmc", tmc);
                }

                String turntype = TNaviTurnIconID.getName(_preRDD.getInteger("ty"));
                item.put("turntype", turntype);
                item.put("turncode", _preRDD.getInteger("ty"));
                item.put("streetName", streetName.get(_preRDD.getString("pos")));
                item.remove("sSI");
                item.remove("eSI");
                items.add(item);
            }

        }

        JSONArray rows = new JSONArray();

        JSONObject json = new JSONObject();
        json.put("duration", dur);
        json.put("distance", dis);
        json.put("item", items);
        json.put("routelatlon", routelatlon);
        rows.add(json);
        JSONObject rResult = new JSONObject();
        rResult.put("rows", rows);

        long step3 = System.currentTimeMillis();
        logger.info("返回值构建耗时:{}ms", step3 - step2);
        logger.info("总耗时:{}ms", step3 - start);

        return rResult.toJSONString();
    }

    /**
     * 公交换乘-经纬度查询
     * <p>
     * 新版本{@link MapbarService#busTransfer2(java.lang.String, java.lang.String, java.lang.String, java.lang.String)}
     */
    public String busTransfer(String orig, String dest, String city, String sort)
            throws ClientProtocolException, IOException {
        String allUrl = busUrl + "getBusTransfersByLonLat.json?customer=2&walkShow=1&encode=utf-8&orig=" + orig
                + "&dest=" + dest + "&city=" + city + "&sort=" + sort;

        String response = HttpClientUtil.doGet(allUrl);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject bus = object.getJSONObject("bus");
        JSONArray item = bus.getJSONArray("item");
        JSONObject result = new JSONObject();

        result.put("rows", item);
        return result.toJSONString();
    }

    public String busCrossCityTransfer(String orig, String dest, String origCity, String destCity)
            throws ClientProtocolException, IOException {
        String allUrl = busUrl + "getBusCrossCity.json?orig=" + orig + "&dest=" + dest + "&origCity=" + origCity
                + "&destCity=" + destCity + "&encode=utf-8&outGb=g02&inGb=g02";

        String response = HttpClientUtil.doGet(allUrl);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject bus = object.getJSONObject("bus");
        JSONArray item = bus.getJSONArray("item");
        JSONObject result = new JSONObject();

        result.put("rows", item);
        return result.toJSONString();
    }

    /**
     * 公交站点关键字查询
     * <p>
     * 新版本{@link MapbarService#busRoute2(java.lang.String, java.lang.String, java.lang.String, java.lang.Boolean, java.lang.Integer, java.lang.Integer)}
     *
     * @param keyword 关键字
     * @param city    城市名称
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    @Deprecated
    public String busRoute(String keyword, String city) throws ClientProtocolException, IOException {
        String allUrl = busUrl + "getRouteNamesByKeyword.json?";
        allUrl = allUrl + "keyword=" + keyword;
        allUrl = allUrl + "&city=" + city;
        allUrl = allUrl + "&all=1&infoFormat=2&encode=utf-8&opposite=true";
        String response = HttpClientUtil.doGet(allUrl);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject routes = object.getJSONObject("routes");
        JSONArray item = routes.getJSONArray("item");
        String count = routes.getString("count");
        JSONObject result = new JSONObject();
        result.put("total", count);
        result.put("rows", item);
        return result.toJSONString();
    }

    /**
     * 公交站点关键字查询
     * <p>
     * 新版本{@link MapbarService#busStation2(java.lang.String, java.lang.String, java.lang.Integer, java.lang.Integer)}
     *
     * @param keyword 关键字
     * @param city    城市名称
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    @Deprecated
    public String busStation(String keyword, String city) throws ClientProtocolException, IOException {
        String allUrl = busUrl + "getStationByKeyword.json?";
        allUrl = allUrl + "keyword=" + keyword;
        allUrl = allUrl + "&city=" + city;
        allUrl = allUrl + "&encode=utf-8";
        allUrl = allUrl + "&outGb=g02";
        String response = HttpClientUtil.doGet(allUrl);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject stations = object.getJSONObject("stations");
        JSONArray station = stations.getJSONArray("station");
        String count = stations.getString("count");
        JSONObject result = new JSONObject();
        result.put("total", count);
        result.put("rows", station);
        return result.toJSONString();
    }

    public String suggest(String keywords, String city)
            throws ClientProtocolException, IOException {

        String allUrl = searchUrl + "suggest?keywords=" + URLEncoder.encode(keywords, "utf-8") + "&city=" + city;
        String response = HttpClientUtil.doGet(allUrl);
        JSONObject data = JSONObject.parseObject(response);
        JSONArray rows = new JSONArray();
        for (int i = 0; i < data.getJSONArray("pois").size(); i++) {
            JSONObject poi = (JSONObject) data.getJSONArray("pois").get(i);
            rows.add(poi);
        }

        JSONObject result = new JSONObject();
        result.put("total", data.getJSONArray("pois").size());
        result.put("rows", rows);

        return result.toJSONString();
    }

    public String replace(String input) {
        String output = input.replace("0", "a");
        output = output.replace("1", "b");
        output = output.replace("2", "e");
        output = output.replace("3", "f");
        output = output.replace("4", "n");
        output = output.replace("5", "m");
        output = output.replace("6", "k");
        output = output.replace("7", "l");
        output = output.replace("8", "g");
        output = output.replace("9", "h");
        return output;
    }

    /* --------------------------------------------- minemap 接口调整 ------------------------------------------------ */

    /**
     * 地理编码评分(新)
     * <p>
     * 原版本方法{@link MapbarService#geocodingScore(java.lang.String, java.lang.String)}
     *
     * @param keywords 关键字名称
     * @param city     adcode/城市名称
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String geocodingScore2(String keywords, String city)
            throws ClientProtocolException, IOException {
        String allUrl = searchUrl + "geo?keywords=" + URLEncoder.encode(keywords, "utf-8");

        if (city != null && !city.equals("")) {
            allUrl = allUrl + "&city=" + city;
        }
        allUrl = allUrl + "&search_type=for_simple";

        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);
        JSONObject data = new JSONObject();
        JSONObject geo = result.getJSONObject("geo");

        JSONObject currentDistrict = result.getJSONObject("currentDistrict");

        JSONArray rows = new JSONArray();
        JSONObject row = new JSONObject();
        row.put("location", geo.getString("location"));
        row.put("score", geo.getDouble("score"));
        row.put("name", currentDistrict.getString("name"));
        row.put("level", currentDistrict.getString("level"));
        row.put("centerPoint", currentDistrict.getString("centerPoint"));
        row.put("adcode", currentDistrict.getString("adcode"));
        rows.add(row);

        data.put("rows", rows);
        return data.toJSONString();
    }

    /**
     * 路线规划(新)
     * <p>
     * 原版本{@link MapbarService#newDriving(java.lang.String, java.lang.String, java.lang.String, int, java.lang.String)}
     *
     * @param sAddr     起点坐标
     * @param toAddr    终点坐标
     * @param wayPoints 途经点，最多5个，用;分隔
     * @param st        算路模式: 0高速优先、1最短距离、2避让高速、3步行模式、4推荐、5经济、6避让拥堵
     * @param avoidArea 避让区域，最多5个，用|分隔
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String newDriving2(String sAddr, String toAddr, String wayPoints, int st, String avoidArea)
            throws ClientProtocolException, IOException {

        long start = System.currentTimeMillis();
        logger.info("start:{}", start);

        String allUrl;
        String slon = new BigDecimal(Double.parseDouble(sAddr.split(",")[0]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
        String slat = new BigDecimal(Double.parseDouble(sAddr.split(",")[1]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();

        String _wayPoints = "";

        if (wayPoints != null && !"".equals(wayPoints)) {
            for (int i = 0; i < wayPoints.split(";").length; i++) {
                String wayPoint = wayPoints.split(";")[i];
                String wlon = new BigDecimal(Double.parseDouble(wayPoint.split(",")[0]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String wlat = new BigDecimal(Double.parseDouble(wayPoint.split(",")[1]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                _wayPoints = _wayPoints + wlon + "," + wlat + ";";
            }
        }
        String tlon = new BigDecimal(Double.parseDouble(toAddr.split(",")[0]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
        String tlat = new BigDecimal(Double.parseDouble(toAddr.split(",")[1]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();

        String _toAddr = _wayPoints + tlon + "," + tlat;

        allUrl = newRouteUrl + "routing?dv=2.1.4&flag=2,3,4,5,6,7,8,ts,10,linkId,11&rpet=2&pet=2&sAddr=" + slon
                + "," + slat + "&toAddr=" + _toAddr;

        // 避让拥堵
        if (st == 6) {
            allUrl = allUrl + "&tmc=" + 1;
        } else {
            allUrl = allUrl + "&st=" + st;
        }
        if (avoidArea != null && !avoidArea.equals("")) {
            String avoidAreaStr = "";
            for (String avoid : avoidArea.split("\\|")) {
                String avoidLon1 = new BigDecimal(Double.parseDouble(avoid.split(",")[0]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLat1 = new BigDecimal(Double.parseDouble(avoid.split(",")[1]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLon2 = new BigDecimal(Double.parseDouble(avoid.split(",")[2]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLat2 = new BigDecimal(Double.parseDouble(avoid.split(",")[3]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                avoidAreaStr = avoidAreaStr + avoidLon1 + "," + avoidLon2 + "," + avoidLat2 + "," + avoidLat1 + "|";

                avoidAreaStr = replace(avoidAreaStr);
            }
            avoidAreaStr = avoidAreaStr.substring(0, avoidAreaStr.length() - 1);
            allUrl = allUrl + "&avoidArea=" + URLEncoder.encode(avoidAreaStr, "utf-8");
        }

        long step1 = System.currentTimeMillis();
        logger.info("构建请求 url:{}ms", step1 - start);

        String response = HttpClientUtil.doGet(allUrl);

        long step2 = System.currentTimeMillis();
        logger.info("请求耗时:{}ms", step2 - step1);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject result = object.getJSONArray("result").getJSONObject(0);
        JSONObject route = result.getJSONObject("route");
        JSONArray segm = route.getJSONArray("segm");
        String firstNM = segm.getJSONObject(0).getString("nm");

        int dur = route.getInteger("dur");
        int dis = route.getInteger("dis");

        /* 1. 构建 routelatlon */
        StringBuilder routelatlon = new StringBuilder();

        /* 2. 构建 items */
        JSONArray dir = route.getJSONArray("dir");

        Map<String, String> streetName = new HashMap<>();
        for (int i = 0; i < dir.size(); i++) {
            JSONObject _dir = dir.getJSONObject(i);
            streetName.put(_dir.getString("pos"), _dir.getString("nm"));
        }

        JSONArray rDD = route.getJSONArray("rDD");//导航数据

        JSONArray items = new JSONArray();
        Integer tmcLv = 0;

        for (int i = 1; i <= rDD.size(); i++) {

            JSONObject _rDD;
            Integer chd = 0;
            Integer eSI = 0;
            if (i < rDD.size()) {
                _rDD = rDD.getJSONObject(i);
                chd = _rDD.getInteger("chd") == null ? 1 : 0;
                eSI = _rDD.getInteger("sSI");
            } else {
                eSI = segm.size();
            }
            JSONObject _preRDD = rDD.getJSONObject(i - 1);

            Integer prdChd = _preRDD.getInteger("chd") == null ? 1 : 0;
            if (prdChd != 0 || chd != 1) {
                JSONObject item = new JSONObject();
                item.put("id", i - 1);

                if (i == 1) {
                    item.put("strguide", _preRDD.getString("tit").replace("{0}", firstNM));
                } else {
                    item.put("strguide", _preRDD.getString("tit").replace("{0}", ""));
                }

                String pos = _preRDD.getString("pos");
                Double lon = Double.parseDouble(pos.split(",")[0]) / HUNDRED_THOUSAND;
                Double lat = Double.parseDouble(pos.split(",")[1]) / HUNDRED_THOUSAND;
                item.put("turnlatlon", lon + "," + lat);
                item.put("distance", _preRDD.getInteger("dis"));

                int sSI = _preRDD.getInteger("sSI");
                List<Object> subSegm = segm.subList(sSI, eSI);

                item.put("sSI", sSI);
                item.put("eSI", eSI);

                if (subSegm.size() > 0) {
                    JSONArray tmc = new JSONArray();
                    String _routelatlon = "";
                    for (int j = 0; j < subSegm.size(); j++) {
                        JSONObject _segm = (JSONObject) subSegm.get(j);

                        String shPos = _segm.getString("shPos");

                        if (_segm.getInteger("tmcLv") != null)
                            tmcLv = _segm.getInteger("tmcLv");

                        String[] lonlat = shPos.split(";");

                        String linklatlon = "";
                        for (int k = 0; k < lonlat.length; k++) {
                            Double _lon = Double.parseDouble(lonlat[k].split(",")[0]) / HUNDRED_THOUSAND;
                            Double _lat = Double.parseDouble(lonlat[k].split(",")[1]) / HUNDRED_THOUSAND;
                            linklatlon = linklatlon + _lon + "," + _lat + ";";
                        }
                        JSONObject _tmc = new JSONObject();
                        _tmc.put("level", tmcLv);
                        _tmc.put("route", linklatlon);
                        tmc.add(_tmc);

                        int flag = j == 0 ? 0 : 1;
                        for (int k = flag; k < lonlat.length; k++) {
                            Double _lon = Double.parseDouble(lonlat[k].split(",")[0]) / HUNDRED_THOUSAND;
                            Double _lat = Double.parseDouble(lonlat[k].split(",")[1]) / HUNDRED_THOUSAND;
                            _routelatlon = _routelatlon + _lon + "," + _lat + ";";
                            routelatlon.append(_lon).append(",").append(_lat).append(";");
                        }
                    }
                    item.put("routelatlon", _routelatlon);
                    item.put("tmc", tmc);
                }

                String turntype = TNaviTurnIconID.getName(_preRDD.getInteger("ty"));
                item.put("turntype", turntype);
                item.put("turncode", _preRDD.getInteger("ty"));
                item.put("streetName", streetName.get(_preRDD.getString("pos")));
                item.remove("sSI");
                item.remove("eSI");
                items.add(item);
            }

        }

        JSONArray rows = new JSONArray();

        JSONObject json = new JSONObject();
        json.put("duration", dur);
        json.put("distance", dis);
        json.put("item", items);
        json.put("routelatlon", routelatlon);
        rows.add(json);
        JSONObject rResult = new JSONObject();
        rResult.put("rows", rows);

        long step3 = System.currentTimeMillis();
        logger.info("返回值构建耗时:{}ms", step3 - step2);
        logger.info("总耗时:{}ms", step3 - start);

        return rResult.toJSONString();
    }

    /**
     * 货车路线规划
     *
     * @param sAddr     起点坐标
     * @param toAddr    终点坐标
     * @param wayPoints 途经点，最多5个，用;分隔
     * @param st        算路模式: 0高速优先、1最短距离、2避让高速、3步行模式、4推荐、5经济、6避让拥堵
     * @param avoidArea 避让区域，最多5个，用|分隔
     * @param vehicle   车辆信息
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String truckDriving(String sAddr, String toAddr, String wayPoints, Integer st, String avoidArea, String vehicle)
            throws ClientProtocolException, IOException {

        long start = System.currentTimeMillis();
        logger.info("start:{}", start);

        String allUrl;
        String slon = new BigDecimal(Double.parseDouble(sAddr.split(",")[0]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
        String slat = new BigDecimal(Double.parseDouble(sAddr.split(",")[1]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();

        String _wayPoints = "";

        if (wayPoints != null && !"".equals(wayPoints)) {
            for (int i = 0; i < wayPoints.split(";").length; i++) {
                String wayPoint = wayPoints.split(";")[i];
                String wlon = new BigDecimal(Double.parseDouble(wayPoint.split(",")[0]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String wlat = new BigDecimal(Double.parseDouble(wayPoint.split(",")[1]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                _wayPoints = _wayPoints + wlon + "," + wlat + ";";
            }
        }
        String tlon = new BigDecimal(Double.parseDouble(toAddr.split(",")[0]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
        String tlat = new BigDecimal(Double.parseDouble(toAddr.split(",")[1]) * HUNDRED_THOUSAND)
                .setScale(0, BigDecimal.ROUND_HALF_UP).toString();

        String _toAddr = _wayPoints + tlon + "," + tlat;

        allUrl = newRouteUrl + "routing?dv=2.1.4&flag=2,3,4,5,6,7,8,ts,10,linkId,11&rpet=2&pet=2&sAddr=" + slon
                + "," + slat + "&toAddr=" + _toAddr;

        // 避让拥堵
        if (st == 6) {
            allUrl = allUrl + "&tmc=" + 1;
        } else {
            allUrl = allUrl + "&st=" + st;
        }
        if (avoidArea != null && !avoidArea.equals("")) {
            String avoidAreaStr = "";
            for (String avoid : avoidArea.split("\\|")) {
                String avoidLon1 = new BigDecimal(Double.parseDouble(avoid.split(",")[0]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLat1 = new BigDecimal(Double.parseDouble(avoid.split(",")[1]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLon2 = new BigDecimal(Double.parseDouble(avoid.split(",")[2]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                String avoidLat2 = new BigDecimal(Double.parseDouble(avoid.split(",")[3]) * HUNDRED_THOUSAND)
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                avoidAreaStr = avoidAreaStr + avoidLon1 + "," + avoidLon2 + "," + avoidLat2 + "," + avoidLat1 + "|";

                avoidAreaStr = replace(avoidAreaStr);
            }
            avoidAreaStr = avoidAreaStr.substring(0, avoidAreaStr.length() - 1);
            allUrl = allUrl + "&avoidArea=" + URLEncoder.encode(avoidAreaStr, "utf-8");
        }

        long step1 = System.currentTimeMillis();
        logger.info("构建请求 url:{}ms", step1 - start);

        String response = HttpClientUtil.doPost(allUrl, vehicle);

        long step2 = System.currentTimeMillis();
        logger.info("请求耗时:{}ms", step2 - step1);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject result = object.getJSONArray("result").getJSONObject(0);
        JSONObject route = result.getJSONObject("route");
        JSONArray segm = route.getJSONArray("segm");
        String firstNM = segm.getJSONObject(0).getString("nm");

        int dur = route.getInteger("dur");
        int dis = route.getInteger("dis");

        /* 1. 构建 routelatlon */
        StringBuilder routelatlon = new StringBuilder();

        /* 2. 构建 items */
        JSONArray dir = route.getJSONArray("dir");

        Map<String, String> streetName = new HashMap<>();
        for (int i = 0; i < dir.size(); i++) {
            JSONObject _dir = dir.getJSONObject(i);
            streetName.put(_dir.getString("pos"), _dir.getString("nm"));
        }

        JSONArray rDD = route.getJSONArray("rDD");//导航数据

        JSONArray items = new JSONArray();
        Integer tmcLv = 0;

        for (int i = 1; i <= rDD.size(); i++) {

            JSONObject _rDD;
            Integer chd = 0;
            Integer eSI = 0;
            if (i < rDD.size()) {
                _rDD = rDD.getJSONObject(i);
                chd = _rDD.getInteger("chd") == null ? 1 : 0;
                eSI = _rDD.getInteger("sSI");
            } else {
                eSI = segm.size();
            }
            JSONObject _preRDD = rDD.getJSONObject(i - 1);

            Integer prdChd = _preRDD.getInteger("chd") == null ? 1 : 0;
            if (prdChd != 0 || chd != 1) {
                JSONObject item = new JSONObject();
                item.put("id", i - 1);

                if (i == 1) {
                    item.put("strguide", _preRDD.getString("tit").replace("{0}", firstNM));
                } else {
                    item.put("strguide", _preRDD.getString("tit").replace("{0}", ""));
                }

                String pos = _preRDD.getString("pos");
                Double lon = Double.parseDouble(pos.split(",")[0]) / HUNDRED_THOUSAND;
                Double lat = Double.parseDouble(pos.split(",")[1]) / HUNDRED_THOUSAND;
                item.put("turnlatlon", lon + "," + lat);
                item.put("distance", _preRDD.getInteger("dis"));

                int sSI = _preRDD.getInteger("sSI");
                List<Object> subSegm = segm.subList(sSI, eSI);

                item.put("sSI", sSI);
                item.put("eSI", eSI);

                if (subSegm.size() > 0) {
                    JSONArray tmc = new JSONArray();
                    String _routelatlon = "";
                    for (int j = 0; j < subSegm.size(); j++) {
                        JSONObject _segm = (JSONObject) subSegm.get(j);

                        String shPos = _segm.getString("shPos");

                        if (_segm.getInteger("tmcLv") != null)
                            tmcLv = _segm.getInteger("tmcLv");

                        String[] lonlat = shPos.split(";");

                        String linklatlon = "";
                        for (int k = 0; k < lonlat.length; k++) {
                            Double _lon = Double.parseDouble(lonlat[k].split(",")[0]) / HUNDRED_THOUSAND;
                            Double _lat = Double.parseDouble(lonlat[k].split(",")[1]) / HUNDRED_THOUSAND;
                            linklatlon = linklatlon + _lon + "," + _lat + ";";
                        }
                        JSONObject _tmc = new JSONObject();
                        _tmc.put("level", tmcLv);
                        _tmc.put("route", linklatlon);
                        tmc.add(_tmc);

                        int flag = j == 0 ? 0 : 1;
                        for (int k = flag; k < lonlat.length; k++) {
                            Double _lon = Double.parseDouble(lonlat[k].split(",")[0]) / HUNDRED_THOUSAND;
                            Double _lat = Double.parseDouble(lonlat[k].split(",")[1]) / HUNDRED_THOUSAND;
                            _routelatlon = _routelatlon + _lon + "," + _lat + ";";
                            routelatlon.append(_lon).append(",").append(_lat).append(";");
                        }
                    }
                    item.put("routelatlon", _routelatlon);
                    item.put("tmc", tmc);
                }

                String turntype = TNaviTurnIconID.getName(_preRDD.getInteger("ty"));
                item.put("turntype", turntype);
                item.put("turncode", _preRDD.getInteger("ty"));
                item.put("streetName", streetName.get(_preRDD.getString("pos")));
                item.remove("sSI");
                item.remove("eSI");
                items.add(item);
            }

        }

        JSONArray rows = new JSONArray();

        JSONObject json = new JSONObject();
        json.put("duration", dur);
        json.put("distance", dis);
        json.put("item", items);
        json.put("routelatlon", routelatlon);
        rows.add(json);
        JSONObject rResult = new JSONObject();
        rResult.put("rows", rows);

        long step3 = System.currentTimeMillis();
        logger.info("返回值构建耗时:{}ms", step3 - step2);
        logger.info("总耗时:{}ms", step3 - start);

        return rResult.toJSONString();
    }

    /**
     * 公交换乘-经纬度查询
     * <p>
     * 原版本{@link MapbarService#busTransfer(java.lang.String, java.lang.String, java.lang.String, java.lang.String)}
     */
    public String busTransfer2(String orig, String dest, String city, String sort)
            throws ClientProtocolException, IOException {
        String allUrl = busUrl + "getBusTransfersByLonLat.json?customer=2&walkShow=1&encode=utf-8&orig=" + orig
                + "&dest=" + dest + "&city=" + city + "&sort=" + sort;

        String response = HttpClientUtil.doGet(allUrl);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject bus = object.getJSONObject("bus");
        bus.remove("taxiCost");
        bus.remove("busrate");

        JSONArray items = bus.getJSONArray("item");
        for (int i = 0; i < items.size(); i++) {
            JSONObject item = items.getJSONObject(i);
            item.remove("texiCost");
            item.remove("busrate");

            JSONArray linedetails = item.getJSONArray("linedetails");

            for (int j = 0; j < linedetails.size(); j++) {
                JSONObject routelatlon = linedetails.getJSONObject(j);
                routelatlon.remove("value");
                routelatlon.remove("isDriving");
                routelatlon.remove("lineid");
                routelatlon.remove("mergeDriveTime");
                routelatlon.remove("mergePinyin");
            }
        }

        JSONObject result = new JSONObject();
        result.put("rows", bus);
        return result.toJSONString();
    }

    /**
     * 公交线路关键字查询
     * <p>
     * 原版本{@link MapbarService#busRoute(java.lang.String, java.lang.String)}
     *
     * @param keyword  关键字
     * @param city     城市名称
     * @param type     查询的方式
     * @param opposite 是否显示返程线路信息
     * @param pn       当前页数
     * @param rn       每页显示数
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String busRoute2(String keyword, String city, String type, Boolean opposite, Integer pn, Integer rn) throws ClientProtocolException, IOException {
        String allUrl = busUrl + "getRouteNamesByKeyword.json?";
        allUrl = allUrl + "keyword=" + keyword;
        allUrl = allUrl + "&city=" + city;
        allUrl = allUrl + "&all=1&infoFormat=2&encode=utf-8&opposite" + opposite;
        allUrl = allUrl + "&type=" + type;
        allUrl = allUrl + "&pn=" + pn;
        allUrl = allUrl + "&rn=" + rn;
        String response = HttpClientUtil.doGet(allUrl);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject routes = object.getJSONObject("routes");
        routes.remove("time");
        routes.put("rows", routes.getJSONArray("item"));
        routes.remove("item");
        return routes.toJSONString();
    }

    /**
     * 公交站点关键字查询(新)
     * <p>
     * 原版本{@link MapbarService#busStation(java.lang.String, java.lang.String)}
     *
     * @param keyword 关键字
     * @param city    城市名称
     * @param pn      当前页数
     * @param rn      每页显示数
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String busStation2(String keyword, String city, Integer pn, Integer rn) throws ClientProtocolException, IOException {
        String allUrl = busUrl + "getStationByKeyword.json?";
        allUrl = allUrl + "keyword=" + keyword;
        allUrl = allUrl + "&city=" + city;
        allUrl = allUrl + "&encode=utf-8";
        allUrl = allUrl + "&outGb=g02";
        allUrl = allUrl + "&pn=" + pn;
        allUrl = allUrl + "&rn=" + rn;
        String response = HttpClientUtil.doGet(allUrl);

        JSONObject object = JSONObject.parseObject(response);
        JSONObject stations = object.getJSONObject("stations");
        JSONArray station = stations.getJSONArray("station");
        String count = stations.getString("count");
        JSONObject result = new JSONObject();
        result.put("total", count);
        result.put("rows", station);
        return result.toJSONString();
    }

    /**
     * 地理编码 POI 查询(新)
     * <p>
     * 原接口{@link MapbarService#geocoding(java.lang.String, java.lang.String)}
     *
     * @param keywords  关键字名称
     * @param city      adcode/名称
     * @param page_num  当前页数，小于1按1处理，大于20按20处理
     * @param page_size 每页记录数，小于1按10处理，大于15按15处理
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String geocoding2(String keywords, String city, Integer page_num, Integer page_size)
            throws ClientProtocolException, IOException {
        String allUrl = searchUrl + "keywords?keywords=" + URLEncoder.encode(keywords, "utf-8");

        if (city != null) {
            allUrl = allUrl + "&city=" + city;
        }
        allUrl = allUrl + "&search_type=for_poi";
        allUrl = allUrl + "&page_num=" + page_num;
        allUrl = allUrl + "&page_size=" + page_size;

        String response = HttpClientUtil.doGet(allUrl);
        JSONObject result = JSONObject.parseObject(response);
        result.remove("statusInfo");
        result.remove("dataType");
        result.remove("filter");
        result.remove("poiStyle");
        result.remove("topicName");
        result.remove("statusCode");
        result.remove("totalCount");
        result.remove("isNearby");
        result.remove("searchType");

        JSONObject currentDistrict = result.getJSONObject("currentDistrict");
        currentDistrict.remove("citycode");
        JSONArray rows = new JSONArray();

        JSONArray pois = result.getJSONArray("pois");
        for (int i = 0; i < pois.size(); i++) {
            JSONObject row = new JSONObject();
            JSONObject poi = pois.getJSONObject(i);
            row.put("name", poi.get("name"));
            row.put("address", poi.get("address"));
            row.put("province", poi.get("province"));
            row.put("city", poi.get("city"));
            row.put("district", poi.get("district"));
            row.put("nid", poi.get("nid"));
            row.put("phone", poi.get("phone"));
            row.put("location", poi.get("location"));
            row.put("naviLocation", poi.get("naviLocation"));
            row.put("distance", poi.get("distance"));
            rows.add(row);
        }
        result.put("rows", rows);
        result.remove("pois");
        return result.toJSONString();
    }

    /**
     * 逆地理编码查询(新)
     * <p>
     * 原版本{@link MapbarService#reverseGeocoding(Double, Double)}
     *
     * @param lon
     * @param lat
     * @param detail
     * @param road
     * @param rowNumber
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String reverseGeocoding2(Double lon, Double lat, Integer detail,
                                    Integer road, Integer rowNumber) throws ClientProtocolException, IOException {
        String allUrl = reverseGeocoding + "/getInverseGeocoding.json?lon=" + lon + "&lat=" + lat + "&language=0&zoom=18";

        if (detail != null) {
            allUrl = allUrl + "&detail=" + detail;
        }
        if (road != null) {
            allUrl = allUrl + "&road=" + road;
        }
        if (rowNumber != null) {
            allUrl = allUrl + "&rowNumber=" + rowNumber;
        }

        String response = HttpClientUtil.doGet(allUrl);

        JSONObject result = JSONObject.parseObject(response);

        result.remove("nation");
        result.remove("poies");
        result.remove("roads");
        result.remove("latlon");
        result.getJSONObject("province").remove("scale");
        result.getJSONObject("city").remove("scale");

        return result.toJSONString();
    }

    /**
     * 周边搜索
     *
     * @param keywords   关键字
     * @param city       adcode/名称
     * @param location   指定位置，和range配合使用
     * @param range      周边搜索指定范围
     * @param pageNum    当前页数，小于1按1处理，大于20按20处理
     * @param pageSize   每页记录数，小于1按10处理，大于15按15处理
     * @param language   搜索内容以及返回结果的语言，默认是中文
     * @param searchType 搜索类型
     * @return
     */
    public String keywordAround(String keywords, String city, String location, String range, Integer pageNum,
                                Integer pageSize, String language, String searchType) throws IOException {
        String allUrl = searchUrl.substring(0, searchUrl.length() - 1) + "?search_type=" + searchType;
        allUrl = allUrl + "&keywords=" + keywords;
        allUrl = allUrl + "&language=" + language;
        allUrl = allUrl + "&city=" + city;
        allUrl = allUrl + "&curr_location=" + location;
        allUrl = allUrl + "&range=" + range;
        allUrl = allUrl + "&pageNum=" + pageNum;
        allUrl = allUrl + "&pageSize=" + pageSize;

        String response = HttpClientUtil.doGet(allUrl);

        JSONObject result = JSONObject.parseObject(response);

        result.remove("statusInfo");
        result.remove("dataType");
        result.remove("filter");
        result.remove("poiStyle");
        result.remove("topicName");
        result.remove("statusCode");
        result.remove("totalCount");
        result.remove("isNearby");
        result.remove("searchType");

        JSONObject currentDistrict = result.getJSONObject("currentDistrict");
        currentDistrict.remove("citycode");

        JSONArray pois = result.getJSONArray("pois");
        for (int i = 0; i < pois.size(); i++) {
            JSONObject poi = pois.getJSONObject(i);
            poi.remove("tag");
            poi.remove("brand");
            poi.remove("confidenceLevel");
            poi.remove("rank");
            poi.remove("photo");
            poi.remove("direct");
            poi.remove("hit");
            poi.remove("point");
            poi.remove("cityPoint");
            poi.remove("border");
            poi.remove("road");
            poi.remove("children");
            poi.remove("score");
            poi.remove("url");
        }
        return result.toJSONString();
    }

    /**
     * 关键字搜索
     *
     * @param keywords   关键字
     * @param city       adcode/名称
     * @param location   指定位置，和range配合使用
     * @param area       当前视野的经纬度坐标
     * @param zoom       缩放级别
     * @param pageNum    当前页数，小于1按1处理，大于20按20处理
     * @param pageSize   每页记录数，小于1按10处理，大于15按15处理
     * @param language   搜索内容以及返回结果的语言，默认是中文
     * @param searchType 搜索类型
     * @return
     */
    public String keywordSearch(String keywords, String city, String location, String area, Integer zoom, Integer pageNum,
                                Integer pageSize, String language, String searchType) throws IOException {
        String allUrl = searchUrl.substring(0, searchUrl.length() - 1) + "?search_type=" + searchType;
        allUrl = allUrl + "&keywords=" + keywords;
        allUrl = allUrl + "&language=" + language;
        allUrl = allUrl + "&city=" + city;
        allUrl = allUrl + "&location=" + location;
        allUrl = allUrl + "&area=" + area;
        allUrl = allUrl + "&zoom=" + zoom;
        allUrl = allUrl + "&pageNum=" + pageNum;
        allUrl = allUrl + "&pageSize=" + pageSize;

        String response = HttpClientUtil.doGet(allUrl);

        JSONObject result = JSONObject.parseObject(response);

        result.remove("statusInfo");
        result.remove("dataType");
        result.remove("filter");
        result.remove("poiStyle");
        result.remove("topicName");
        result.remove("statusCode");
        result.remove("totalCount");
        result.remove("isNearby");
        result.remove("searchType");
        result.remove("nearbyParam");

        JSONObject currentDistrict = result.getJSONObject("currentDistrict");
        currentDistrict.remove("citycode");

        JSONArray pois = result.getJSONArray("pois");
        for (int i = 0; i < pois.size(); i++) {
            JSONObject poi = pois.getJSONObject(i);
            poi.remove("tag");
            poi.remove("brand");
            poi.remove("confidenceLevel");
            poi.remove("rank");
            poi.remove("photo");
            poi.remove("direct");
            poi.remove("hit");
            poi.remove("point");
            poi.remove("cityPoint");
            poi.remove("border");
            poi.remove("road");
            poi.remove("children");
            poi.remove("score");
        }

        return result.toJSONString();
    }

    /**
     * 行政区搜索
     *
     * @param keywords 关键字
     * @param location 指定位置，和range配合使用
     * @return
     */
    public String adminSearch(String keywords, String location) throws IOException {

        if (StringUtil.isEmpty(location)) {
            location = ADMIN_BEIJING_CENTER_LOCATION;
        }

        String allUrl = searchUrl.substring(0, searchUrl.length() - 1)
                + "?keywords=" + keywords + "&curr_location=" + location;

        String response = HttpClientUtil.doGet(allUrl);

        JSONObject object = JSONObject.parseObject(response);

        JSONObject result = object.getJSONObject("districtSwap");
        result.put("citycode", object.getJSONObject("currentDistrict").get("citycode"));

        return result.toJSONString();
    }
}
